using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace BardsTaleMapViewer {
  public class Item {
    public int _index;
    public Items _items;

    public Item (int index, Items items) {
      _index = index;
      _items = items;
    }

    public string Name {
      get {
        return (_items._itemsName [_index]);
      }
    }

    public string TypeString {
      get {
        return (_items._itemTypesString [Type]);
      }
    }

    private int ItemsAttackEffectAndType {
      get {
        return (_items._itemsAttackEffectAndType [_index]);
      }
    }

    public int Type {
      get {
        return ((ItemsAttackEffectAndType >> 0) & 0x0F);
      }
    }

    public int AttackEffect {
      get {
        return ((ItemsAttackEffectAndType >> 4) & 0x0F);
      }
    }

    public string AttackEffectString {
      get {
        return (MonsterType._attackEffectsString [AttackEffect]);
      }
    }

    public int AllowedCategoriesToEquipMask {
      get {
        return (_items._itemsAllowedCategoryToEquipMask [_index]);
      }
    }

    public int Unk03 {
      get {
        return (_items._itemsUnk03 [_index]);
      }
    }

    public int Unk01AndArmorClass {
      get {
        return (_items._itemsUnk01AndArmorClass [_index]);
      }
    }

    public int ArmorClass {
      get {
        return ((Unk01AndArmorClass >> 0) & 0x0F);
      }
    }

    public int Unk01 {
      get {
        return ((Unk01AndArmorClass >> 4) & 0x0F);
      }
    }

    public int SpecialUnk02AndType {
      get {
        return (_items._itemsSpecialUnk02AndType [_index]);
      }
    }

    public int SpecialType {
      get {
        return ((SpecialUnk02AndType >> 0) & 0x7F);
      }
    }

    public string SpecialTypeString (bool html) {
      if (SpecialType <= 15) {
        if (SpecialType == 1)
          return ("Regen health point");
        else if (SpecialType == 2)
          return ("Regen spell point");
        else if (SpecialType == 4)
          return ("Halve spell point cost");
        else if (SpecialType == 5)
          return ("Infinite songs");
        else if (SpecialType == 6)
          return ("BonusSavingThrow: 2 HideInShadows: 100%");
        else if (SpecialType == 9)
          return ("Kill the Crystal Golem");
        else if (SpecialType == 14)
          return ("Mangar's Tower key");
        else if (SpecialType != 0)
          return ("SpecialType " + SpecialType);
      }
      else {
        int spellIndex = _items._itemSpecialTypesSpellIndex [SpecialType];
        if (spellIndex < _items._game._spellbook._spells.Count) {
          Spell spell = _items._game._spellbook._spells [spellIndex];
          return (string.Format ("Spell #{0}: {2}", spellIndex, html ? "<br>" : " ", html ? spell.ShortDescHtml : spell.ShortDesc));
        }
        else
          throw new Exception ();
        //return (string.Format ("Spell #{0}", spellIndex));
      }
      if (SpecialType == 0)
        return (html ? "&nbsp;" : "-");
      return ("TODO");
    }

    public int SpecialUnk02 {
      get {
        return ((SpecialUnk02AndType >> 7) & 0x01);
      }
    }

    public int WeaponDamageBonusAndArmorClassNotUsed {
      get {
        return (_items._itemsWeaponDamageBonusAndArmorClassNotUsed [_index]);
      }
    }

    public int WeaponArmorClassNotUsed {
      get {
        return ((WeaponDamageBonusAndArmorClassNotUsed >> 0) & 0x0F);
      }
    }

    public int WeaponDamageBonus {
      get {
        return ((WeaponDamageBonusAndArmorClassNotUsed >> 4) & 0x0F);
      }
    }

    public string WeaponDamageBonusString {
      get {
        if (WeaponDamageBonus == 0)
          return ("-");
        else
          return (string.Format ("+{0}", WeaponDamageBonus));
      }
    }

    public int WeaponAttackDices {
      get {
        return (_items._itemsWeaponAttackDices [_index]);
      }
    }

    public int WeaponAttackDicesB {
      get {
        return ((WeaponAttackDices >> 0) & 0x1F);
      }
    }

    public int WeaponAttackDicesA {
      get {
        return ((WeaponAttackDices >> 5) & 0x07);
      }
    }

    public string WeaponAttackDicesString {
      get {
        // Weapon
        if (Type == 1)
          return (Dice.DiceWithMinMaxString ((int) Math.Pow (2, WeaponAttackDicesA + 2), WeaponAttackDicesB + 1, 0, WeaponDamageBonus, -2, 1, 1, 2, 2));
        else
          return ("-");
      }
    }

    //public string UseString {
    //  get {
    //    if (_index == 41)
    //      return ("No effect");
    //    else {
    //      if (SpecialUnk02 <= 15)
    //        return ("Can't be used");
    //      else {
    //        int spellIndex = _items._itemSpecialsSpellIndex [SpecialUnk02];
    //        if (spellIndex < _items._game._spellbook._spells.Count)
    //          return (string.Format ("Spell #{0}: {1}", spellIndex, _items._game._spellbook._spells [spellIndex].ShortDesc));
    //        else
    //          return (string.Format ("Spell #{0}", spellIndex));
    //      }
    //    }
    //    return ("TODO");
    //  }
    //}

    public string AllowedClassesString {
      get {
        int allowedCategoriesToEquipMask = AllowedCategoriesToEquipMask;
        StringBuilder sb = new StringBuilder ();
        for (int i = 0; i < _items._classesAllowedCategoriesToEquipBits.Count; i++) {
          string classString = _items._classesString [i];
          int classAllowedCategoriesToEquipBits = _items._classesAllowedCategoriesToEquipBits [i];
          if ((classAllowedCategoriesToEquipBits & allowedCategoriesToEquipMask) != 0)
            sb.Append (classString [0]);
          else
            sb.Append ("-");
        }
        return sb.ToString ();
      }
    }

    public string Uses {
      get {
        if (SpecialType >= 48)
          return ("1 use");
        else
          return ("1/64");
      }
    }

    public string DifficultiesString {
      get {
        return (_items._game._beastiary.GetDifficultiesString (_index));
      }
    }

    public int CostBits {
      get {
        return (_items._itemsCostBits [_index]);
      }
    }

    public int Cost {
      get {
        int costBits = CostBits;
        int BBBBB = (costBits >> 3) & 0x1F;
        int AAA = (costBits >> 0) & 0x07;
        int cost = BBBBB * ((int) Math.Pow (10, AAA));
        return (cost);
      }
    }

    public void Dump () {
      //Console.WriteLine (string.Format ("{0,3}  {1,1}  {2,1}  {3,-4}  {4,-15}  {5,-22}  {6,2}  {7,-9}  {8,2}  {9,3}  {10,-22}  {11}",
      //  _index, ClassString, Level, Acronym, Name, FunctionName, SpellPointCost, TargetTypeString, BitsAllowedInCombat, BitsAllowedOutCombat, BitsParamString, AttributeString));
      int typeLength = Game.Lengthest (_items._itemTypesString);
      int nameLength = Game.Lengthest (_items._itemsName);
      int nbClasses = _items._classesString.Count;
      int attackEffectLength = Game.Lengthest (MonsterType._attackEffectsString);

      StringBuilder sb = new StringBuilder ();
      sb.AppendFormat ("{0,3}", _index);
      sb.AppendFormat ("  {0,-8}", DifficultiesString);
      sb.AppendFormat ("  {0,-" + typeLength + "}", TypeString);
      sb.AppendFormat ("  {0,-" + nameLength + "}", Name);
      sb.AppendFormat ("  {0,6}", Cost);
      sb.AppendFormat ("  {0,-" + nbClasses + "}", AllowedClassesString);
      sb.AppendFormat ("  {0,-13}", WeaponAttackDicesString);
      //sb.AppendFormat ("  {0,-6}", WeaponDamageBonusString);
      sb.AppendFormat ("  {0,-" + attackEffectLength + "}", AttackEffectString);
      sb.AppendFormat ("  {0,2}", (ArmorClass == 0) ? "-" : ArmorClass.ToString ());
      //sb.AppendFormat ("  {0,5}", (Unk01 == 0) ? "-" : Unk01.ToString ());
      //sb.AppendFormat ("  {0,5}", (Unk03 == 0) ? "-" : Unk03.ToString ());
      //sb.AppendFormat ("  {0,5}", SpecialUnk02);
      sb.AppendFormat ("  {0,-5}", Uses);
      sb.AppendFormat ("  {0}", SpecialTypeString (false));
      Console.WriteLine (sb.ToString ());
    }

    public StringBuilder DumpHtml () {
      //Console.WriteLine (string.Format ("{0,3}  {1,1}  {2,1}  {3,-4}  {4,-15}  {5,-22}  {6,2}  {7,-9}  {8,2}  {9,3}  {10,-22}  {11}",
      //  _index, ClassString, Level, Acronym, Name, FunctionName, SpellPointCost, TargetTypeString, BitsAllowedInCombat, BitsAllowedOutCombat, BitsParamString, AttributeString));
      int typeLength = Game.Lengthest (_items._itemTypesString);
      int nameLength = Game.Lengthest (_items._itemsName);
      int nbClasses = _items._classesString.Count;
      int attackEffectLength = Game.Lengthest (MonsterType._attackEffectsString);

      StringBuilder sb = new StringBuilder ();
      sb.AppendFormat ("<tr>");
      sb.AppendFormat ("<th>{0}</th>", _index);
      sb.AppendFormat ("<th style='font-family: monospace;font-size: 13px;white-space:nowrap;'>{0}</th>", DifficultiesString);
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", TypeString);
      sb.AppendFormat ("<td style='white-space:nowrap'>{0}</td>", Name);
      sb.AppendFormat ("<th>{0}</th>", Cost);
      sb.AppendFormat ("<th style='font-family: monospace;font-size: 13px;white-space:nowrap;'>{0}</th>", AllowedClassesString);
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", WeaponAttackDicesString);
      //sb.AppendFormat ("  {0,-6}", WeaponDamageBonusString);
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", AttackEffectString);
      sb.AppendFormat ("<th>{0}</th>", (ArmorClass == 0) ? "-" : ArmorClass.ToString ());
      //sb.AppendFormat ("  {0,5}", (Unk01 == 0) ? "-" : Unk01.ToString ());
      //sb.AppendFormat ("  {0,5}", (Unk03 == 0) ? "-" : Unk03.ToString ());
      //sb.AppendFormat ("  {0,5}", SpecialUnk02);
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", Uses);
      sb.AppendFormat ("<td style='white-space:nowrap'>{0}</td>", SpecialTypeString (true));
      sb.AppendFormat ("</tr>");
      return (sb);
    }
  }
}
